//采用懒汉模式，模拟实现单例模式
public class Demo_Singleton {
    //懒汉模式 - 创建对象，需要的时候再进行实例化
    private volatile static Demo_Singleton singleton = null;
    //单例模式 - 不允许调用构造函数进行实例化，用private封装
    private Demo_Singleton(){ }
    //不允许创建对象，只能通过类名调用，用static修饰
    public static Demo_Singleton getSingleton(){
        //多个线程访问，每次都会获取锁，会出现效率低的问题 - 如果实例化过了，就不需要再获取锁
        if(singleton == null){
            synchronized (Demo_Singleton.class){
                //如果singleton为空，多个线程同时调用这个方法，可能会有线程安全问题 - 加锁
                if(singleton == null){
                    //第一次使用时才创建对象，避免用不到时的开销
                    //new对象的时候，分三步：申请内存空间，构造对象，将内存地址赋值给引用
                    //如果出现指令重排序，有恰好有线程调用对象，还是会出现线程安全问题 - volatile防止指令重排序
                    singleton = new Demo_Singleton();
                }
            }
        }
        return singleton;
    }
}
